from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
from cryptography.fernet import Fernet
import os
import base64


class City(models.Model):
    """城市模型"""
    name = models.CharField(max_length=100, unique=True, verbose_name="城市名称")
    code = models.CharField(max_length=10, unique=True, verbose_name="城市代码") 
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
        db_table = 'city'
        verbose_name = '城市'
        verbose_name_plural = '城市'

    def __str__(self):
        return self.name


class DataCenter(models.Model):
    """机房模型"""
    name = models.CharField(max_length=100, verbose_name="机房名称")
    code = models.CharField(max_length=20, unique=True, verbose_name="机房代码")
    city = models.ForeignKey(City, on_delete=models.CASCADE, related_name='datacenters', verbose_name="所属城市")
    address = models.TextField(blank=True, verbose_name="详细地址")
    contact_person = models.CharField(max_length=50, blank=True, verbose_name="联系人")
    contact_phone = models.CharField(max_length=20, blank=True, verbose_name="联系电话")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
        db_table = 'datacenter'
        verbose_name = '机房'
        verbose_name_plural = '机房'
        unique_together = ['city', 'name']

    def __str__(self):
        return f"{self.city.name}-{self.name}"


class Host(models.Model):
    """主机模型"""
    STATUS_CHOICES = [
        ('online', '在线'),
        ('offline', '离线'),
        ('maintenance', '维护中'),
    ]

    hostname = models.CharField(max_length=100, unique=True, verbose_name="主机名")
    ip_address = models.GenericIPAddressField(unique=True, verbose_name="IP地址")
    datacenter = models.ForeignKey(DataCenter, on_delete=models.CASCADE, related_name='hosts', verbose_name="所属机房")
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='offline', verbose_name="状态")
    os_type = models.CharField(max_length=50, verbose_name="操作系统类型")
    cpu_cores = models.IntegerField(default=1, verbose_name="CPU核数")
    memory_gb = models.IntegerField(default=1, verbose_name="内存(GB)")
    disk_gb = models.IntegerField(default=100, verbose_name="磁盘(GB)")
    ssh_port = models.IntegerField(default=22, verbose_name="SSH端口")
    description = models.TextField(blank=True, verbose_name="描述")
    last_ping_time = models.DateTimeField(null=True, blank=True, verbose_name="最后ping时间")
    last_ping_result = models.BooleanField(default=False, verbose_name="最后ping结果")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
        db_table = 'host'
        verbose_name = '主机'
        verbose_name_plural = '主机'

    def __str__(self):
        return f"{self.hostname}({self.ip_address})"

    @property
    def city(self):
        """获取主机所在城市"""
        return self.datacenter.city


class HostCredential(models.Model):
    """主机凭证模型 - 存储加密的root密码"""
    host = models.OneToOneField(Host, on_delete=models.CASCADE, related_name='credential', verbose_name="关联主机")
    username = models.CharField(max_length=50, default='root', verbose_name="用户名")
    encrypted_password = models.TextField(verbose_name="加密密码")
    password_updated_at = models.DateTimeField(auto_now_add=True, verbose_name="密码更新时间")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")

    class Meta:
        db_table = 'host_credential'
        verbose_name = '主机凭证'
        verbose_name_plural = '主机凭证'

    def __str__(self):
        return f"{self.host.hostname}-{self.username}"

    @staticmethod
    def get_encryption_key():
        """获取或生成加密密钥"""
        key_file = 'encryption.key'
        if os.path.exists(key_file):
            with open(key_file, 'rb') as f:
                return f.read()
        else:
            key = Fernet.generate_key()
            with open(key_file, 'wb') as f:
                f.write(key)
            return key

    def set_password(self, password):
        """设置加密密码"""
        key = self.get_encryption_key()
        f = Fernet(key)
        self.encrypted_password = f.encrypt(password.encode()).decode()
        self.password_updated_at = timezone.now()

    def get_password(self):
        """获取解密密码"""
        key = self.get_encryption_key()
        f = Fernet(key)
        return f.decrypt(self.encrypted_password.encode()).decode()


class HostStatistics(models.Model):
    """主机统计模型 - 按城市和机房维度统计"""
    city = models.ForeignKey(City, on_delete=models.CASCADE, verbose_name="城市")
    datacenter = models.ForeignKey(DataCenter, on_delete=models.CASCADE, verbose_name="机房")
    total_hosts = models.IntegerField(default=0, verbose_name="主机总数")
    online_hosts = models.IntegerField(default=0, verbose_name="在线主机数")
    offline_hosts = models.IntegerField(default=0, verbose_name="离线主机数")
    maintenance_hosts = models.IntegerField(default=0, verbose_name="维护中主机数")
    statistics_date = models.DateField(verbose_name="统计日期")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")

    class Meta:
        db_table = 'host_statistics'
        verbose_name = '主机统计'
        verbose_name_plural = '主机统计'
        unique_together = ['city', 'datacenter', 'statistics_date']

    def __str__(self):
        return f"{self.statistics_date}-{self.city.name}-{self.datacenter.name}"


class RequestLog(models.Model):
    """请求日志模型 - 用于记录请求耗时"""
    path = models.CharField(max_length=500, verbose_name="请求路径")
    method = models.CharField(max_length=10, verbose_name="请求方法")
    duration_ms = models.FloatField(verbose_name="耗时(毫秒)")
    status_code = models.IntegerField(verbose_name="状态码")
    user = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name="用户")
    ip_address = models.GenericIPAddressField(verbose_name="IP地址")
    user_agent = models.TextField(blank=True, verbose_name="用户代理")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")

    class Meta:
        db_table = 'request_log'
        verbose_name = '请求日志'
        verbose_name_plural = '请求日志'
        indexes = [
            models.Index(fields=['created_at']),
            models.Index(fields=['path']),
            models.Index(fields=['duration_ms']),
        ]

    def __str__(self):
        return f"{self.method} {self.path} - {self.duration_ms}ms"
